{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests,os,json,base64\n",
    "from scrapy.selector import Selector\n",
    "from  binascii import hexlify\n",
    "from Crypto.Cipher import AES\n",
    "\n",
    "class Encrypyed():\n",
    "    '''传入歌曲的ID，加密生成'params'、'encSecKey 返回'''\n",
    "    def __init__(self):\n",
    "        self.pub_key = '010001'\n",
    "        self.modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'\n",
    "        #self.nonce = '0CoJUm6Qyw8W8jud'.encode('utf-8')\n",
    "        self.nonce = '0CoJUm6Qyw8W8jud'\n",
    "\n",
    "    def create_secret_key(self, size):\n",
    "        return hexlify(os.urandom(size))[:16].decode('utf-8')\n",
    "\n",
    "    def aes_encrypt(self,text, key):\n",
    "        iv = '0102030405060708'.encode('utf-8')\n",
    "        pad = 16 - len(text) % 16\n",
    "        text = text + pad * chr(pad)\n",
    "        encryptor = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv)\n",
    "        result = encryptor.encrypt(text.encode('utf-8'))\n",
    "        result_str = base64.b64encode(result).decode('utf-8')\n",
    "        return result_str\n",
    "\n",
    "    def rsa_encrpt(self,text, pubKey, modulus):\n",
    "        text = text[::-1]\n",
    "        rs = pow(int(hexlify(text.encode('utf-8')), 16), int(pubKey, 16), int(modulus, 16))\n",
    "        return format(rs, 'x').zfill(256)\n",
    "\n",
    "    def work(self,ids,br=128000):\n",
    "        text = {'ids': [ids], 'br': br, 'csrf_token': ''}\n",
    "        text = json.dumps(text)\n",
    "        i=self.create_secret_key(16)\n",
    "        encText =self.aes_encrypt(text, self.nonce)\n",
    "        encText=self.aes_encrypt(encText,i)\n",
    "        encSecKey=self.rsa_encrpt(i,self.pub_key,self.modulus)\n",
    "        data = {'params': encText, 'encSecKey': encSecKey}\n",
    "        return data\n",
    "\n",
    "    def search(self,text):\n",
    "        #print(text)\n",
    "        text = json.dumps(text)\n",
    "        i = self.create_secret_key(16)\n",
    "        encText = self.aes_encrypt(text, self.nonce)\n",
    "        encText = self.aes_encrypt(encText, i)\n",
    "        encSecKey = self.rsa_encrpt(i, self.pub_key, self.modulus)\n",
    "        data = {'params': encText, 'encSecKey': encSecKey}\n",
    "        return data\n",
    "\n",
    "\n",
    "class search():\n",
    "    '''跟歌单直接下载的不同之处，1.就是headers的referer\n",
    "                              2.加密的text内容不一样！\n",
    "                              3.搜索的URL也是不一样的\n",
    "        输入搜索内容，可以根据歌曲ID进行下载，大家可以看我根据跟单下载那章，自行组合\n",
    "                                '''\n",
    "    def __init__(self):\n",
    "        self.headers = {\n",
    "            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',\n",
    "            'Host': 'music.163.com',\n",
    "            'Referer': 'http://music.163.com/search/'} ###!!注意，搜索跟歌单的不同之处！！\n",
    "        self.main_url='http://music.163.com/'\n",
    "        self.session = requests.Session()\n",
    "        self.session.headers=self.headers\n",
    "        self.ep=Encrypyed()\n",
    "\n",
    "    def search_song(self, search_content,search_type=1, limit=9):\n",
    "        \"\"\"\n",
    "        根据音乐名搜索\n",
    "      :params search_content: 音乐名\n",
    "      :params search_type: 不知\n",
    "      :params limit: 返回结果数量\n",
    "      return: 可以得到id 再进去歌曲具体的url\n",
    "        \"\"\"\n",
    "        url = 'http://music.163.com/weapi/cloudsearch/get/web?csrf_token='\n",
    "        text = {'s': search_content, 'type': search_type, 'offset': 0, 'sub': 'false', 'limit': limit}\n",
    "        data = self.ep.search(text)\n",
    "        resp = self.session.post(url, data=data)\n",
    "        result = resp.json()\n",
    "        l = []\n",
    "        if result['result']['songCount']<= 0:\n",
    "            print('搜不到！！')\n",
    "        else:\n",
    "            songs = result['result']['songs']\n",
    "            for song in songs:\n",
    "                song_id,song_name,singer,alia = song['id'],song['name'],song['ar'][0]['name'],song['al']['name']\n",
    "#                 print(song_id,song_name,singer,alia)\n",
    "                l.append((song_id,song_name,singer))\n",
    "        return l\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    d=search()\n",
    "    #d.search_song('爱多一次痛多一次'.encode(\"utf-8\"))\n",
    "    d.search_song('林俊杰')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'type': 1, 'sub': 'false', 'limit': 9, 's': '林俊杰', 'offset': 0}\n"
     ]
    }
   ],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(108485, 'Always Online'),\n",
       " (108245, '爱笑的眼睛'),\n",
       " (40147554, '关键词'),\n",
       " (108478, '醉赤壁'),\n",
       " (25727803, '修炼爱情'),\n",
       " (108914, '江南'),\n",
       " (29848657, '手心的蔷薇'),\n",
       " (108493, '我还想她'),\n",
       " (37196629, '不为谁而作的歌')]"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "def play(id=None):\n",
    "    if id is not None:\n",
    "        url=\"https://music.163.com/song/media/outer/url?id=\"+str(id)\n",
    "        headers = {\n",
    "            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36',\n",
    "            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',\n",
    "        }\n",
    "        r = requests.get(url,headers=headers,allow_redirects=False)\n",
    "        redi_url = r.headers['Location']\n",
    "        print(redi_url)\n",
    "        os.system(\"mpg123 \"+redi_url.replace('https','http'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'s': '林俊杰', 'offset': 0, 'limit': 9, 'sub': 'false', 'type': 1}\n",
      "https://m10.music.126.net/20190428004721/756f80a3899409e023a4c60713f1659f/ymusic/b250/623f/65c6/d40e637edffd95499d424eb3f9ae70f8.mp3\n"
     ]
    }
   ],
   "source": [
    "l = d.search_song('林俊杰')\n",
    "play(l[0][0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/rapiro/\n",
      "Listening...\n",
      "stop\n"
     ]
    }
   ],
   "source": [
    "import sys\n",
    "import os\n",
    "import yaml\n",
    "import re\n",
    "from aip import AipSpeech\n",
    "xiaobai_dir = \"/rapiro/\"\n",
    "\n",
    "sys.path.append(xiaobai_dir)\n",
    "from xiaobai import XiaoBai\n",
    "\n",
    "xiaobai = None\n",
    "def callback():\n",
    "    global xiaobai\n",
    "    notify_sound = xiaobai_dir+'resources/ding.wav'\n",
    "    os.system(\"aplay \"+notify_sound)\n",
    "    print(\"key word detected\")\n",
    "    if xiaobai is not None:\n",
    "        res = xiaobai.listen_and_recognize()\n",
    "        print(\"你  ：\"+res)\n",
    "        m = re.search('(我想听|播放)(.+?)(的歌$|$)', res)\n",
    "        if m is not None:\n",
    "            search = m.groups()[1].replace('的',' ')\n",
    "            l = d.search_song(search)\n",
    "            if len(l)>0:\n",
    "                reply = \"为您播放\"+l[0][2]+\",\"+l[0][1]\n",
    "                print(\"小白：\"+reply)\n",
    "                xiaobai.speak(reply)\n",
    "                play(l[0][0])\n",
    "keyword_model = xiaobai_dir+'resources/小白.pmdl'\n",
    "xiaobai = XiaoBai(keyword_model=keyword_model,callback=callback)\n",
    "xiaobai.listen_for_keyword()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
